package com.shusl.config;

import com.shusl.entity.Perm;
import com.shusl.service.impl.CustomAuthenticationFailureHandler;
import com.shusl.service.impl.CustomAuthenticationSuccessHandler;
import com.shusl.service.impl.PermServiceImpl;
import com.shusl.service.impl.RoleServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.List;
//SpringSecurity 新版2.7+

@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig  {

    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Autowired
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
    /**
     * 授权
     * @return
     */
//    @Bean
//    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//        // 定制请求的授权规则
//        // 首页所有人可以访问
//        //不用权限的写，要权限的用/**
//        http.authorizeRequests().antMatchers("/").permitAll()
//                .antMatchers("/level1/**").hasRole("vip1")
//                .antMatchers("/level2/**").hasRole("vip2")
//                .antMatchers("/level3/**").hasRole("vip3")
//                .antMatchers("/admin/**").hasAuthority("ADMIN")
//                .and()
//                .formLogin()
//                .loginPage("/toLogin")
//                .loginProcessingUrl("/toLogin")
//                .successHandler(customAuthenticationSuccessHandler)  // 配置自定义登录成功处理器
//                .failureHandler(customAuthenticationFailureHandler)  // 配置自定义登录失败处理器
//                .and()
//                .logout()
//                .and()
//                .csrf().disable()
//                .rememberMe().rememberMeParameter("rememberMe");
//        return http.build();
//    }
    @Autowired
    private PermServiceImpl permService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests((authorize) -> {
                    // 允许登录页面匿名访问
                    authorize.antMatchers("/toLogin","/").permitAll();
                    // 直接使用全局变量中的权限数据
                    //所以，就算权限表中什么都没有，也不能使得所有权限都是被允许的，反而都需要登录，不过postman没有登录概念，所以返回html文件
                    List<Perm> permissions = permService.list();
                    for (Perm permission : permissions) {
                        if (permission.getAnonStatus() == 0) {
                            authorize.antMatchers(permission.getPermUrl()).hasAuthority(permission.getName());
                        } else {
                            authorize.antMatchers(permission.getPermUrl()).permitAll();
                        }
                    }
                    // 其他通用配置
                    authorize.anyRequest().authenticated();//则其他均需要登录型验证
                })
                .formLogin()
                .loginPage("/toLogin")
                .loginProcessingUrl("/toLogin")//重写定向登录界面，否则是login
                .successHandler(customAuthenticationSuccessHandler)
                .failureHandler(customAuthenticationFailureHandler)
                .and()
                .logout()//集成登出
                .and()
                .csrf().disable()//有关安全设置，自动打开避免遭受get攻击
                .rememberMe().rememberMeParameter("rememberMe");
        return http.build();
    }

    /**
     * 认证
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(); // 使用BCrypt加密算法
    }
    @Bean//如果数据库写法不是固定型写法，就需要更改这里的查询方法
    public UserDetailsService userDetailsService() {
        JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager(dataSource);

        // 自定义SQL查询：查询用户信息
        userDetailsService.setUsersByUsernameQuery(
                "SELECT u.name AS username, u.password, true AS enabled FROM user u WHERE u.name = ?"
        );

        // 自定义SQL查询：查询用户角色
        userDetailsService.setAuthoritiesByUsernameQuery(//原来你的参数是sql语句字符串，而不是String 变量而已
                "SELECT u.name AS username, p.name AS authority\n" +
                        "FROM perm p\n" +
                        "JOIN role_perm rp ON p.id = rp.perm_id\n" +
                        "JOIN user_role ur ON rp.role_id = ur.role_id\n" +
                        "JOIN user u ON ur.user_id = u.id\n" +
                        "WHERE u.name = ?\n" +
                        "GROUP BY p.name;"
        );
        return userDetailsService;
    }
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }
    @Autowired//注入数据库
    private DataSource dataSource;
}
